package com.lion.ball.common.spring.apisignature;

import com.lion.ball.common.base.exceptions.CommonException;
import com.lion.ball.common.spring.annotations.ApiSignature;
import jakarta.servlet.http.HttpServletRequest;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

/**
 * @author Chris Chan
 * Create On 2025/8/6 上午10:55
 * Use for: 接口验证签名
 * Explain:
 */
@Aspect
@Component
public class SignatureAspect {
    @Autowired
    private SignatureSecretManager secretManager;

    @Around("@annotation(apiSignature)||@within(apiSignature)")
    public Object checkSignature(ProceedingJoinPoint joinPoint, ApiSignature apiSignature) throws Throwable {
        HttpServletRequest request =
                ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();

        // 1. 获取签名参数
        //分配的应用id
        String appId = request.getHeader("X-App-Id");
        //时间戳
        String timestampStr = request.getHeader("X-Timestamp");
        //签名
        String signature = request.getHeader("X-Signature");

        // 获取秘钥
        String appSecret = secretManager.getSecret();

        System.out.println("appId = " + appId);
        System.out.println("timestampStr = " + timestampStr);
        System.out.println("signature = " + signature);

        // 2. 校验签名
        if (appId == null || timestampStr == null || signature == null) {
            throw CommonException.of(500, "签名参数错误");
        }

        // 3. 校验时间戳 单位:毫秒（时间戳与当前时间差不能超过5分钟）
        // 校验时间戳
        if(timestampStr.length() != 13) {
            throw CommonException.of(500, "时间戳格式错误");
        }
        try {
            long timestamp = Long.parseLong(timestampStr);
            long now = System.currentTimeMillis();
            if (now - timestamp > 1000 * 60 * 5) {
                throw CommonException.of(500, "签名过期");
            }
        } catch (NumberFormatException e) {
            throw CommonException.of(500, "时间戳格式错误");
        }


        // 4. 校验签名
        String origin = appId + "\n" + appSecret + "\n" + timestampStr;
        if (!SignatureUtil.verify(appSecret, origin, signature)) {
            throw CommonException.of(500, "签名错误");
        }

        return joinPoint.proceed();
    }
}